// 创建一个立即执行函数来避免全局作用域污染
(function(window) {
    // 检查是否已经存在MapService
    if (window.MapService) {
        return;
    }

    // 坐标转换算法
    function wgs84ToGcj02(lng, lat) {
        const ee = 0.00669342162296594323;
        const a = 6378245.0;
        let dLat = transformLat(lng - 105.0, lat - 35.0);
        let dLng = transformLng(lng - 105.0, lat - 35.0);
        const radLat = lat / 180.0 * Math.PI;
        const magic = Math.sin(radLat);
        const magic1 = 1 - ee * magic * magic;
        const sqrtMagic = Math.sqrt(magic1);
        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic1 * sqrtMagic) * Math.PI);
        dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * Math.PI);
        return [lng + dLng, lat + dLat];
    }

    function gcj02ToWgs84(lng, lat) {
        const [gcjLng, gcjLat] = wgs84ToGcj02(lng, lat);
        return [lng * 2 - gcjLng, lat * 2 - gcjLat];
    }

    function bd09ToGcj02(lng, lat) {
        const x = lng - 0.0065;
        const y = lat - 0.006;
        const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * Math.PI);
        const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * Math.PI);
        return [z * Math.cos(theta), z * Math.sin(theta)];
    }

    function gcj02ToBd09(lng, lat) {
        const z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * Math.PI);
        const theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * Math.PI);
        return [z * Math.cos(theta) + 0.0065, z * Math.sin(theta) + 0.006];
    }

    function transformLat(x, y) {
        let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0 * Math.PI)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y * Math.PI / 30.0)) * 2.0 / 3.0;
        return ret;
    }

    function transformLng(x, y) {
        let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0 * Math.PI)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x / 30.0 * Math.PI)) * 2.0 / 3.0;
        return ret;
    }

    // 检查是否已加载Leaflet
    if (typeof L === 'undefined') {
        console.error('Leaflet is not loaded. Please include Leaflet before loading this script.');
        return;
    }

    // 导出MapService类
    class MapService {
        constructor(mapId = 'map', wsUrl = 'ws://localhost:3000') {
            this.map = null;          // Leaflet地图实例
            this.mapId = mapId;       // 地图容器ID
            this.markers = [];       // 存储所有标记的数组
            this.lines = [];         // 存储所有线条的数组
            this.polygons = [];      // 存储所有多边形的数组(包括边界)
            this.wsUrl = wsUrl;      // WebSocket服务地址
            this.ws = null;          // WebSocket连接实例
            this.markersLayer = null; // 标记图层组(在init中初始化)
            this.linesLayer = null;   // 线条图层组(在init中初始化)
            this.polygonsLayer = null; // 多边形图层组(在init中初始化)
            this.connectWebSocket();
        }

        // 连接WebSocket
        connectWebSocket() {
            try {
                this.ws = new WebSocket(this.wsUrl);
                
                this.ws.onopen = () => {
                    console.log('WebSocket连接已建立');
                };

                this.ws.onmessage = (event) => {
                    try {
                        const response = JSON.parse(event.data);
                        
                        // 先添加服务器响应到日志
                        addLog(response, 'server');
                        console.log('收到服务器响应:', response);
                        
                        // 如果命令执行失败，显示错误信息
                        if (!response.success) {
                            console.error('命令执行失败:', response.error);
                            return;
                        }

                        // 执行接收到的命令
                        if (response && response.command && response.params) {
                            console.log('准备执行命令:', response.command, '参数:', response.params);
                            switch (response.command) {
                
                                                               
                                case 'setView':
                                    console.log('执行 setView 命令');
                                    try {
                                        this.setView(
                                            response.params.lat,
                                            response.params.lng,
                                            response.params.zoom,
                                            false  // 不要通知服务器
                                        );
                                        console.log('设置视图完成');
                                        this.sendFeedback('setView', true, '设置视图成功');
                                    } catch (error) {
                                        console.error('设置视图失败:', error);
                                        this.sendFeedback('setView', false, '设置视图失败: ' + error.message);
                                    }
                                    break;

                                case 'addMarker':
                                    console.log('执行 addMarker 命令');
                                    try {
                                        this.addMarker(
                                            response.params.coordinate[0],
                                            response.params.coordinate[1],
                                            response.params.color,
                                            response.params.size,
                                            false  // 不要通知服务器
                                        );
                                        console.log('添加标记完成');
                                        this.sendFeedback('addMarker', true, '添加标记成功');
                                    } catch (error) {
                                        console.error('添加标记失败:', error);
                                        this.sendFeedback('addMarker', false, '添加标记失败: ' + error.message);
                                    }
                                    break;

  
                                    

                                default:
                                    console.warn('未知命令:', response.command);
                            }
                        } else {
                            console.warn('收到的消息格式不正确:', response);
                        }
                    } catch (error) {
                        console.error('解析服务器响应失败:', error);
                    }
                };

                this.ws.onerror = (error) => {
                    console.error('WebSocket错误:', error);
                };

                this.ws.onclose = () => {
                    console.log('WebSocket连接已关闭');
                };
            } catch (error) {
                console.error('创建WebSocket连接失败:', error);
            }
        }

        // 发送命令到服务器
        sendCommand(command, params) {
            if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
                console.error('WebSocket未连接');
                return;
            }

            try {
                const message = {
                    command: command,
                    params: params || {}
                };
                this.ws.send(JSON.stringify(message));
            } catch (error) {
                console.error('发送命令失败:', error);
            }
        }

        // 发送反馈到服务器
        sendFeedback(command, success, message) {
            if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
                console.error('WebSocket未连接，无法发送反馈');
                return;
            }

            try {
                const feedback = {
                    type: 'feedback',
                    command,
                    success,
                    message,
                    timestamp: new Date().toISOString()
                };
                this.ws.send(JSON.stringify(feedback));
            } catch (error) {
                console.error('发送反馈失败:', error);
            }
        }

        init(center = [39.9042, 116.4074], zoom = 13) {
            this.map = L.map(this.mapId).setView(center, zoom);
            
            // 创建基础图层
            const baseLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                maxZoom: 19,
                attribution: '© OpenStreetMap contributors'
            }).addTo(this.map);

            // 创建覆盖图层组
            const overlays = {
                "标记": L.layerGroup(),
                "线条": L.layerGroup(),
                "多边形": L.layerGroup()
            };

            // 添加图层控制
            L.control.layers({
                "OpenStreetMap": baseLayer
            }, overlays, {
                collapsed: false
            }).addTo(this.map);

            // 更新图层引用
            this.markersLayer = overlays["标记"];
            this.linesLayer = overlays["线条"]; 
            this.polygonsLayer = overlays["多边形"];

            // 发送初始化命令
            this.sendCommand('init', { center, zoom });

            return this;
        }

        setView(lat, lng, zoom, shouldNotify = true) {
            this.map.setView([lat, lng], zoom);
            
            // 只有在需要通知服务器时才发送命令
            if (shouldNotify) {
                this.sendCommand('setView', { lat, lng, zoom });
            }
        }

        // 添加点标记
        addMarker(lat, lng, color = '#3388ff', size = 5, shouldNotify = true) {
            const point = L.circleMarker([lat, lng], {
                radius: size,
                fillColor: color,
                color: color,
                weight: 1,
                opacity: 1,
                fillOpacity: 0.8
            }).addTo(this.markersLayer);
            
            this.markers.push(point);
            // **自动缩放到点**
            this.map.flyTo([lat, lng], this.map.getZoom(), { duration: 1 });
            
            // 只有在需要通知服务器时才发送命令
            if (shouldNotify) {
                this.sendCommand('addMarker', { 
                    coordinate: [lat, lng],
                    color,
                    size
                });
            }
            
            return point;
        }
    }

    // 将MapService添加到全局作用域
    window.MapService = MapService;
})(window);
